package cn.ibizlab.util.repository;

import cn.ibizlab.util.domain.EntityMongo;
import cn.ibizlab.util.filter.MongoQueryContext;
import cn.ibizlab.util.helper.CachedBeanCopier;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.query.MongoEntityInformation;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.data.support.PageableExecutionUtils;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

public class IBZMongoSimpleRepository<T extends EntityMongo, ID> implements  IBZMongoRepository<T, ID> {

    private final MongoOperations mongoOperations;
    private final MongoEntityInformation<T, ID> entityInformation;

    public IBZMongoSimpleRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) {

        this.entityInformation = metadata;
        this.mongoOperations = mongoOperations;
    }

    @Override
    public <S extends T> S save(S entity) {
        //更新空值处理
        ID id = entityInformation.getId(entity);
        if (id != null) {
            Optional<T> op = findById(id);
            if (op.isPresent()) {
                T t = op.get();
                CachedBeanCopier.copy(entity,t);
                entity = (S) t;
            }
        }
        return  entity;
    }

    @Override
    public <S extends T> Page<T> query(MongoQueryContext mongoQueryContext) {
        Query query = mongoQueryContext.getSearchCond();
        query.with(mongoQueryContext.getPageable());
        if(mongoQueryContext.getPageSort()!=null)
            query.with(mongoQueryContext.getPageSort());
        List<T> list = mongoOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName());

        return PageableExecutionUtils.getPage(list, mongoQueryContext.getPageable(),
                () -> mongoOperations.count(query, entityInformation.getJavaType(), entityInformation.getCollectionName()));
    }

    @Override
    public <S extends T> List<S> saveAll(Iterable<S> entities) {
        return null;
    }

    @Override
    public Optional<T> findById(ID id) {
        return Optional.empty();
    }

    @Override
    public boolean existsById(ID id) {
        return false;
    }

    @Override
    public List<T> findAll() {
        return null;
    }

    @Override
    public Iterable<T> findAllById(Iterable<ID> ids) {
        return null;
    }

    @Override
    public long count() {
        return 0;
    }

    @Override
    public void deleteById(ID id) {

    }

    @Override
    public void delete(T entity) {

    }

    @Override
    public void deleteAllById(Iterable<? extends ID> ids) {

    }

    @Override
    public void deleteAll(Iterable<? extends T> entities) {

    }

    @Override
    public void deleteAll() {

    }

    @Override
    public List<T> findAll(Sort sort) {
        return null;
    }

    @Override
    public Page<T> findAll(Pageable pageable) {
        return null;
    }

    @Override
    public <S extends T> S insert(S entity) {
        return null;
    }

    @Override
    public <S extends T> List<S> insert(Iterable<S> entities) {
        return null;
    }

    @Override
    public <S extends T> Optional<S> findOne(Example<S> example) {
        return Optional.empty();
    }

    @Override
    public <S extends T> List<S> findAll(Example<S> example) {
        return null;
    }

    @Override
    public <S extends T> List<S> findAll(Example<S> example, Sort sort) {
        return null;
    }

    @Override
    public <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) {
        return null;
    }

    @Override
    public <S extends T> long count(Example<S> example) {
        return 0;
    }

    @Override
    public <S extends T> boolean exists(Example<S> example) {
        return false;
    }

    @Override
    public <S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction) {
        return null;
    }
}
